#ifndef _M_BUF_H_
#define _M_BUF_H_
#include "util.hpp"
#include <vector>
#include <cassert>

namespace mylog{
#define DEFAULT_BUFFER_SIZE (1*1024*1024)
#define THRESHOLD_BUFFER_SIZE (8*1024*1024)  //阈值--小于阈值大小就翻倍增长，达到就线性增长
#define INCREMENT_BUFFER_SIZE (1*1024*1024)  //线性增长时的增量
class Buffer{
public:
Buffer():_read_idx(0), _write_idx(0){_buffer.resize(DEFAULT_BUFFER_SIZE);}
//向缓冲区写入数据
void push(const char* data,size_t len){
   //缓冲区可写空间不足
   //1.固定大小，直接返回
    //if(len>writeAbleSize())return;
    //2.扩容，用于极限压力测试
    ensureEnoughSize(len);
//将数据拷贝进缓冲区
    std::copy(data,data+len,&_buffer[_write_idx]);
//移动写指针
    moveWriter(len);

}
//返回可读数据的起始地址
const char* begin(){
    return &_buffer[_read_idx];
}
//返回可读数据的长度
size_t readAbleSize(){
    return (_write_idx-_read_idx);
}
//返回可写区域的长度
size_t writeAbleSize(){
    return (_buffer.size()- _write_idx);  //别用_buffer.capacity()
}
//对读写指针进行向后移动操作
void moveWriter(size_t len){
    assert(len<=writeAbleSize());
    _write_idx+=len;
}
void moveReader(size_t len){
    assert(len<=readAbleSize());
    _read_idx+=len;
}
//重置读写位置，初始化缓冲区时使用
void reset(){
    _write_idx=0;
    _read_idx=0;
}
//交换缓冲区
void swap(Buffer &buffer){  //这里不要加const,swap设计对buffer的修改
    _buffer.swap(buffer._buffer);
    std::swap(_read_idx,buffer._read_idx);
    std::swap(_write_idx,buffer._write_idx);
}

bool empty(){
    return (_read_idx==_write_idx);
}
private:
void ensureEnoughSize(size_t len){
    if(len<=writeAbleSize())return;//不需要扩容
    size_t new_size=0;
    if(_buffer.size()<THRESHOLD_BUFFER_SIZE){//小于阈值就翻倍增长
        new_size=_buffer.size()*2+len;          
    }else{
        new_size=_buffer.size()+INCREMENT_BUFFER_SIZE+len;  //大于等于阈值就线性增长
    }
    _buffer.resize(new_size);
}
private:
std::vector<char> _buffer; //直接存放格式化后的日志消息字符串，减少LogMsg对象频繁构造，可进行一次性IO操作
size_t _read_idx; //当前可读数据的起始下标位置
size_t _write_idx; //当前可写区域的起始下标位置
};

}
#endif